package com.huitone.smspfm.interfacz.tasks;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import com.huitone.smspfm.interfacz.logger.ExtLogger;

import com.bin.common.utils.StringUtils;
import com.huitone.smspfm.context.utils.ContextUtils;
import com.huitone.smspfm.interfacz.core.AppStaticConfigs;
import com.huitone.smspfm.interfacz.dao.SvrNodeDefMapper;
import com.huitone.smspfm.interfacz.dao.entity.SvrNodeDef;
import com.huitone.smspfm.interfacz.dao.entity.SvrNodeDefExample;

/**   
* @Title ClientsHostPortTestTask.java 
* @Package com.huitone.smspfm.interfacz.tasks 
* @Description 用于测试业务端接收上行短信及报告信息的服务是否可用,若不可用则强制关闭推送
* @author ybliang   
* @date 2017年8月15日 上午11:20:55 
* @version V1.0   
*/
public class ClientsHostPortTestTask extends Thread {
	
	private static final ExtLogger logger = ExtLogger.create(ClientsHostPortTestTask.class);
	
	private int timeOut = 5000;
	
	private long excuteIntevel = 60000;
	
	private int maxTryTimes = 3;
	
	private Map<String, Integer> counter = new HashMap<String, Integer>();
	
	private boolean keepGoing = true;
	
	private ExecutorService executorService = Executors.newFixedThreadPool(AppStaticConfigs.clientConnCheckPoolsize);

	@Override
	public void run() {
		
		excuteIntevel = AppStaticConfigs.clientConnCheckPertime > 0 ? AppStaticConfigs.clientConnCheckPertime : excuteIntevel;
		
		while(!this.isInterrupted() && isKeepGoing()) {
			
			Iterator<Entry<String, SvrNodeDef>> iterator = AppStaticConfigs.svrNodeDefMap.entrySet().iterator();
			
			while (iterator.hasNext()) {
				
				Entry<String, SvrNodeDef> entry = iterator.next();
				
				executorService.execute(new Runnable() {
					
					@Override
					public void run() {
						
						String key = entry.getKey();
						SvrNodeDef svrNodeDef = entry.getValue();
						
						String serverIp = svrNodeDef.getServerIp();
						Integer serverPort = svrNodeDef.getServerPort();
						
						String acceptReport = svrNodeDef.getAcceptReport();
						String accetpMo = svrNodeDef.getAcceptMo();
						
						Socket socket = new Socket();
						
						if (!StringUtils.equals(acceptReport, "1") || !StringUtils.equals(accetpMo, "1")) {
							
							if (!counter.containsKey(key)) {
								counter.put(key, 0);
							}
							
							try {
								
								socket.connect(new InetSocketAddress(serverIp, serverPort), timeOut);
								
								if (counter.get(key) < 0) {
									counter.put(key, 0);
								}
								
								if (StringUtils.equals(acceptReport, "2") || StringUtils.equals(accetpMo, "2")) {
									logger.info("业务端服务连接测试正常[srvNode:" + svrNodeDef.getSvrNode() + ", host:" + serverIp + ", port:" + serverPort + "], 连接成功!");
								}
								
								if (AppStaticConfigs.clientDeliverAndReportAutoOnOff) {
									
									if (counter.get(key) < maxTryTimes - 1) {
										counter.put(key, counter.get(key) + 1);
									} else {
										if (StringUtils.equals(acceptReport, "2")) {
											logger.info("业务端:" + svrNodeDef.getSvrNode() + "服务多次测试连接成功,将恢复其报告信息推送!");
											AppStaticConfigs.svrNodeDefMap.get(key).setAcceptReport("0");
											
											SvrNodeDefMapper svrNodeDefMapper = ContextUtils.getBean2(SvrNodeDefMapper.class);
											
											SvrNodeDefExample example = new SvrNodeDefExample();
											example.createCriteria().andSvrNodeEqualTo(key);
											
											SvrNodeDef record = new SvrNodeDef();
											record.setAcceptReport("0");
											
											svrNodeDefMapper.updateByExampleSelective(record, example);
										}
										if (StringUtils.equals(accetpMo, "2")) {
											logger.info("业务端:" + svrNodeDef.getSvrNode() + "服务多次测试连接成功,将恢复其上行短信推送!");
											AppStaticConfigs.svrNodeDefMap.get(key).setAcceptMo("0");
											
											SvrNodeDefMapper svrNodeDefMapper = ContextUtils.getBean2(SvrNodeDefMapper.class);
											
											SvrNodeDefExample example = new SvrNodeDefExample();
											example.createCriteria().andSvrNodeEqualTo(key);
											
											SvrNodeDef record = new SvrNodeDef();
											record.setAcceptMo("0");
											
											svrNodeDefMapper.updateByExampleSelective(record, example);
										}
									}
								}
								
							} catch (IOException e) {
								
								if (counter.get(key) > 0) {
									counter.put(key, 0);
								}
								
								if ((StringUtils.equals(acceptReport, "0") || acceptReport == null) || (StringUtils.equals(accetpMo, "0") || accetpMo == null)) {
									logger.warn("业务端服务连接测试异常[srvNode:" + svrNodeDef.getSvrNode() + ", host:" + serverIp + ", port:" + serverPort + "], " + e.getMessage());
								}
								
								if (AppStaticConfigs.clientDeliverAndReportAutoOnOff) {
									
									if (counter.get(key) > (- maxTryTimes + 1)) {
										counter.put(key, counter.get(key) - 1);
									} else {
										if (StringUtils.equals(acceptReport, "0") || acceptReport == null) {
											logger.warn("业务端:" + svrNodeDef.getSvrNode() + "服务多次测试连接失败,将强行关闭其报告信息推送!");
											AppStaticConfigs.svrNodeDefMap.get(key).setAcceptReport("2");
											
											SvrNodeDefMapper svrNodeDefMapper = ContextUtils.getBean2(SvrNodeDefMapper.class);
											
											SvrNodeDefExample example = new SvrNodeDefExample();
											example.createCriteria().andSvrNodeEqualTo(key);
											
											SvrNodeDef record = new SvrNodeDef();
											record.setAcceptReport("2");
											
											svrNodeDefMapper.updateByExampleSelective(record, example);
										}
										if (StringUtils.equals(accetpMo, "0") || accetpMo == null) {
											logger.warn("业务端:" + svrNodeDef.getSvrNode() + "服务多次测试连接失败,将强行关闭其上行短信推送!");
											AppStaticConfigs.svrNodeDefMap.get(key).setAcceptMo("2");
											
											SvrNodeDefMapper svrNodeDefMapper = ContextUtils.getBean2(SvrNodeDefMapper.class);
											
											SvrNodeDefExample example = new SvrNodeDefExample();
											example.createCriteria().andSvrNodeEqualTo(key);
											
											SvrNodeDef record = new SvrNodeDef();
											record.setAcceptMo("2");
											
											svrNodeDefMapper.updateByExampleSelective(record, example);
										}
									}
								}
								
							} finally {
								try {
									socket.close();
								} catch (IOException e) {
									logger.warn(e.getMessage());
								}
							}
						}
					}
				});
			}
			
			try {
				Thread.sleep(excuteIntevel);
			} catch (InterruptedException e) {}
		}
		logger.info("用于测试业务端接收上行短信及报告信息的服务 任务已经退出");
	}

	public boolean isKeepGoing() {
		return keepGoing;
	}

	public void setKeepGoing(boolean keepGoing) {
		this.keepGoing = keepGoing;
	}

	@Override
	public void destroy() {
		this.setKeepGoing(false);
		this.interrupt();
	}

}
